
package com.idealighter.game.games.tongbiniuniu.manager;

import com.alibaba.fastjson.TypeReference;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.core.common.Game;
import com.idealighter.game.games.common.niuniu.NiuNiuCard;
import com.idealighter.game.games.common.niuniu.NiuNiuCardsType;
import com.idealighter.game.games.common.niuniu.NiuNiuCardsTypeComparator;
import com.idealighter.game.games.common.niuniu.NiuNiuCardsTypeGetter;
import com.idealighter.game.games.tongbiniuniu.struct.TongBiNiuNiuSeat;
import com.idealighter.game.games.tongbiniuniu.struct.TongBiNiuNiuTable;
import com.idealighter.game.prizepool.manager.PlayerPrizePoolMgrScript;
import com.idealighter.game.prizepool.manager.RoomPrizePoolMgrScript;
import com.idealighter.game.prizepool.struct.control.TongBiNiuNiuControl;
import com.idealighter.game.prizepool.struct.player.PlayerPrizePool;
import com.idealighter.game.prizepool.struct.room.ControlStrategy;
import com.idealighter.game.prizepool.struct.room.RoomPrizePool;
import com.idealighter.utils.code.RandCodeUtil;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * . 通比牛牛控制 .
 * 
 * @date 2016年2月17日 上午10:46:55
 */
@Singleton
public class TongBiNiuNiuControlScript {

  private static final Logger LOG = LoggerFactory.getLogger(TongBiNiuNiuControlScript.class);
  private static final TypeReference<TongBiNiuNiuControl> TONGBI_NIUNIU_CONTROL_TYPE =
      new TypeReference<TongBiNiuNiuControl>() {};

  // 控制手牌数量(控制时，提前随机生成的手牌数量)
  private static final int CONTROL_HAND_CARDS_NUM = 10;

  @Inject
  private TongBiNiuNiuMsgMgr msgMgr;
  @Inject
  private TongBiNiuNiuMgr tongBiMgr;

  @Inject
  private PlayerPrizePoolMgrScript playerPrizePoolMgr;
  @Inject
  private RoomPrizePoolMgrScript roomPrizePoolMgr;

  /**
   * 控制玩家发牌, 玩家和机器人玩才控制.
   * 
   * @param table .
   */
  public void controlDealCards(TongBiNiuNiuTable table) {
    boolean hasPlayer = false;
    boolean hasRobot = false;

    for (TongBiNiuNiuSeat s : table.seats) {
      if (s.getPlayerId() > 0) {
        if (s.isRobot()) {
          hasRobot = true;
        } else {
          hasPlayer = true;
        }
      }
    }

    // 玩家和机器人玩才控制，个人奖池控制优先房间奖池控制
    if (hasPlayer && hasRobot) {
      LinkedList<List<NiuNiuCard>> sortedCardsList = new LinkedList<>();
      int cardIndex = 0;
      for (int i = 0; i < CONTROL_HAND_CARDS_NUM; i++) {
        sortedCardsList
            .add(table.cards.subList(cardIndex, cardIndex += TongBiNiuNiuMgr.PLAYER_CARDS));
      }

      // 玩家的牌进行排序
      sortedCardsList.sort((cards1, cards2) -> {
        NiuNiuCardsType cards1Type = NiuNiuCardsTypeGetter.getCardsType(cards1, new ArrayList<>());
        NiuNiuCardsType cards2Type = NiuNiuCardsTypeGetter.getCardsType(cards2, new ArrayList<>());
        if (NiuNiuCardsTypeComparator.compare(cards1, cards1Type, cards2, cards2Type)) {
          return 1;
        } else {
          return -1;
        }
      });

      List<Integer> winner = Lists.newArrayList();
      for (TongBiNiuNiuSeat seat : table.seats) {
        if (seat.getPlayerId() > 0) {
          if (seat.isRobot()) {
            continue;
          }
          if (playerPrizePoolControlDealCards(seat, winner)) {
            continue;
          }
          if (roomPrizePoolControlDealCards(seat, winner)) {
            continue;
          }
          if (RandCodeUtil.randomBoolean()) {
            winner.add(seat.getOrder());
          }
        }
      }
      controlDealCards(table, winner, sortedCardsList);
    } else {
      normalDealCards(table);
    }
    resultCalculate(table);
    balanceControl(table);
  }

  /**
   * 控制发牌 .
   * 
   * @param table .
   * @param winner .
   * @param robot .
   * @param loser .
   * @param sortedCardsList .
   */
  private void controlDealCards(TongBiNiuNiuTable table, List<Integer> winner,
      LinkedList<List<NiuNiuCard>> sortedCardsList) {
    if (winner.size() == 0) {
      int winIndex = RandCodeUtil.random(1, 3);
      Set<Integer> li = Sets.newConcurrentHashSet();
      for (TongBiNiuNiuSeat seat : table.seats) {
        if (seat.getPlayerId() == 0) {
          continue;
        }
        if (seat.isRobot()) {
          int loseIndex;
          for (;;) {

            loseIndex = RandCodeUtil.random(4, 8);
            if (!li.contains(loseIndex)) {
              li.add(loseIndex);
              break;
            }
          }
          // dealPlayerCards(seat, sortedCardsList.removeFirst());
          dealPlayerCards(seat, sortedCardsList.get(loseIndex));
          // dealPlayerCards(seat, sortedCardsList.removeLast());

        } else {
          dealPlayerCards(seat, sortedCardsList.get(winIndex));

        }
      }
      return;
    }
    int winOrder = winner.get(RandCodeUtil.random(0, winner.size() - 1));
    int winIndex = RandCodeUtil.random(7, 9);
    Set<Integer> li = Sets.newConcurrentHashSet();
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getOrder() == winOrder) {
        // dealPlayerCards(seat, sortedCardsList.removeLast());
        dealPlayerCards(seat, sortedCardsList.get(winIndex));
      } else {
        int loseIndex;
        for (;;) {
          loseIndex = RandCodeUtil.random(1, 5);
          if (!li.contains(loseIndex)) {
            li.add(loseIndex);
            break;
          }
        }
        // dealPlayerCards(seat, sortedCardsList.removeFirst());
        dealPlayerCards(seat, sortedCardsList.get(loseIndex));
      }
    }
  }

  /**
   * 个人控制 .
   * 
   * @param seat 座位信息.
   * @param wininer .
   * @return
   */
  private boolean playerPrizePoolControlDealCards(TongBiNiuNiuSeat seat, List<Integer> wininer) {
    // 控制输赢的玩家
    PlayerPrizePool prizePool =
        playerPrizePoolMgr.prizePool(seat.getPlayerId(), Game.TONGBI_NIUNIU);

    if (prizePool != null && prizePool.getPrize().get() != 0) {
      TongBiNiuNiuControl control = prizePool.control(TONGBI_NIUNIU_CONTROL_TYPE);
      // 控制输赢的玩家的输赢标识
      boolean controlSeatWin = RandCodeUtil
          .random(control.getLoseRatio() + control.getWinRatio()) >= control.getLoseRatio();
      if (controlSeatWin) {
        wininer.add(seat.getOrder());
      }
      return true;
    }

    return false;
  }

  /**
   * 房间控制 .
   * 
   * @param seat 座位信息.
   * @param winner .
   * @return
   */
  private boolean roomPrizePoolControlDealCards(TongBiNiuNiuSeat seat, List<Integer> winner) {
    TongBiNiuNiuTable table = seat.table;
    // 控制输赢的玩家
    RoomPrizePool roomPrizePool =
        roomPrizePoolMgr.roomPrizePool(seat.getPlayerId(), Game.TONGBI_NIUNIU, table.room.getId());

    if (roomPrizePool != null) {
      // 房间奖池控制策略
      ControlStrategy strategy = roomPrizePool.abledControlStrategy();
      // 控制输赢的玩家的输赢标识
      boolean controlSeatWin;

      if (strategy != null) { // 有控制策略
        // 牛牛控制
        TongBiNiuNiuControl control = strategy.control(TONGBI_NIUNIU_CONTROL_TYPE);
        controlSeatWin = RandCodeUtil
            .random(control.getLoseRatio() + control.getWinRatio()) >= control.getLoseRatio();
      } else { // 没有随机输赢
        controlSeatWin = RandCodeUtil.randomBoolean();
      }
      if (controlSeatWin) {
        winner.add(seat.getOrder());
      }

      return true;
    }

    return false;
  }

  /**
   * 正常发牌 .
   * 
   * @param table .
   */
  private void normalDealCards(TongBiNiuNiuTable table) {
    List<NiuNiuCard> tableCards = table.cards;
    int cardIndex = 0;
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getPlayerId() > 0) {
        dealPlayerCards(seat,
            tableCards.subList(cardIndex, cardIndex += TongBiNiuNiuMgr.PLAYER_CARDS));
      }
    }
  }

  /**
   * 发牌 .
   * 
   * @param seat 座位信息.
   * @param cards .
   */
  private void dealPlayerCards(TongBiNiuNiuSeat seat, List<NiuNiuCard> cards) {
    NiuNiuCardsType seatCardsType = NiuNiuCardsTypeGetter.getCardsType(cards, seat.bestCards);
    seat.cards.clear();
    seat.cards.addAll(cards);
    seat.cardsType = seatCardsType;
    msgMgr.sendDealCardsMsg(seat);
    LOG.info("[通比牛牛]发送玩家[{}][{}]牌[{}]", seat.getPlayerId(), seat.getPlayerName(), seat.bestCards);
  }

  /**
   * 计算结果 .
   *
   * @param table .
   */
  private void resultCalculate(TongBiNiuNiuTable table) {
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getPlayerId() == 0) {
        continue;
      }
      for (TongBiNiuNiuSeat seat1 : table.seats) {
        if (seat1.getPlayerId() == 0) {
          continue;
        }
        if (seat.getPlayerId() == seat1.getPlayerId()) {
          continue;
        }
        boolean win = NiuNiuCardsTypeComparator.compare(seat.cards, seat.cardsType, seat1.cards,
            seat1.cardsType);
        if (win) {
          seat.power++;
        }
      }
    }

    /**
     * 最大的牌值 .
     */
    int power = 0;
    int multiple = 1;
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getPlayerId() == 0) {
        continue;
      }
      if (seat.power > power) {
        power = seat.power;
      }
    }
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getPlayerId() == 0) {
        continue;
      }
      if (seat.power == power) {
        multiple = seat.cardsType.multiple;
        break;
      }
    }
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getPlayerId() == 0) {
        continue;
      }
      if (seat.power == power) {
        seat.billChips = multiple * (table.totalChips - seat.betedchips);
      } else {
        seat.billChips = -seat.betedchips * multiple;
      }
    }
  }

  /**
   * 结算修改个人或房间奖池 .
   *
   * @param table .
   */
  public void balanceControl(TongBiNiuNiuTable table) {
    for (TongBiNiuNiuSeat seat : table.seats) {
      if (seat.getPlayerId() == 0) {
        continue;
      }
      if (seat.isRobot()) {
        continue;
      }
      PlayerPrizePool playerPrizePools =
          playerPrizePoolMgr.prizePool(seat.getPlayerId(), Game.TONGBI_NIUNIU);
      if (playerPrizePools != null) {
        if (playerPrizePools.getPrize().get() != 0) {
          long totalGold = tongBiMgr.convertGold(table.room.getId().intValue(), seat.billChips);
          long prize = playerPrizePools.getPrize().get();
          if (prize > 0) {
            prize = prize - totalGold;
            prize = prize < 0 ? 0 : prize;
          } else if (prize < 0) {
            prize = prize - totalGold;
            prize = prize > 0 ? 0 : prize;
          }
          playerPrizePools.getPrize().getAndSet(prize);
          continue;
        }
      }
      RoomPrizePool seatRoomPrizePool = roomPrizePoolMgr.roomPrizePool(seat.getPlayerId(),
          Game.TONGBI_NIUNIU, table.room.getId());
      if (seatRoomPrizePool != null) {
        long totalGold = tongBiMgr.convertGold(table.room.getId().intValue(), seat.billChips);
        long prize = seatRoomPrizePool.getPrize().get();
        prize -= totalGold;
        seatRoomPrizePool.getPrize().getAndSet(prize);
      }
    }
  }
}
